#pragma once
#include<jsoncpp/json/json.h>
#include"socket.hpp"
#include<functional>


class Request
{
public:
    Request()
    {

    }

    Request(int x,int y ,char oper)
    :_x(x)
    ,_y(y)
    ,_oper(oper)
    {

    }

    ~Request()
    {

    }

    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;
        return writer.write(root);
    }

    void Deserialize(const std::string& jsonstr)
    {
        Json::Value root;
        Json::Reader reader;
        reader.parse(jsonstr,root);
        _x =  root["x"].asInt();
        _y  =  root["y"].asInt();
        _oper = root["oper"].asInt();   
    }

    int GetX()
    {
        return _x;
    }

    int GetY()
    {
        return _y;
    }

    char GetOper()
    {
        return _oper;
    }

private:
    int _x;
    int _y;
    char _oper; 
};


class Response
{
public:
    Response(int result,int code)
    :_result(result)
    ,_code(code)
    {
        
    }

    Response()
    {

    }

    void Show()
    {
        std::cout << _result <<"[" << _code << "]" << std::endl;
    }

    ~Response()
    {

    }

    std::string Serialize()
    {   
        Json::Value root;
        Json::FastWriter writer;
        root["result"] = _result;
        root["code"] = _code;
        return writer.write(root);
    }


    void Deserialize(const std::string& jsonstr)
    {
        Json::Value root;
        Json::Reader reader;
        reader.parse(jsonstr,root);
        _result = root["result"].asInt(); 
        _code = root["code"].asInt();
    }


private:
    int _result;
    int _code;
};

const std::string sep("\r\n");

using func_t = std::function<Response(Request)>;

class Protocol
{
public:
    Protocol(func_t func)
    :_func(func)
    {

    }

    Protocol()
    {

    }

    ~Protocol()
    {

    }

    std::string Encode(const std::string&  jsonstr)  
    {
        int  n = jsonstr.size();
        return std::to_string(n) + sep+jsonstr + sep;
    }

    bool Decode(std::string& buffer_queue,std::string& jsonstr)
    {
        int pos = buffer_queue.find(sep);
        if(pos == -1)
        {   
            return false;
        }
        std::string jsonlenstr = buffer_queue.substr(0,pos);
        int jsonlen =  std::stoi(jsonlenstr);
        int  len =  jsonlen + 2*sep.size() + jsonlenstr.size();
        if(buffer_queue.size() < len)
        {   
            return false;
        }
        jsonstr =  buffer_queue.substr(pos + sep.size(),jsonlen);
        buffer_queue.erase(0,len);
        return true;
    }
    

    void GetRequest(std::shared_ptr<Socket>& sockfd,const InetAddr& client)
    {
        std::string buffer_queue;
        while(true)
        {
            int n = sockfd->Read(buffer_queue);
            if(n == 0)
            {
                LOG(LogLevel::INFO)<<"client quit["<<client.GetIp() << ":"<<client.GetPort()<<"]";
                break;
            }
            std::string rjsonstr;
            if(Decode(buffer_queue,rjsonstr))   
            {
                LOG(LogLevel::INFO) << rjsonstr << ",来自" << client.GetIp() << ":" << client.GetPort();
                Request request;
                request.Deserialize(rjsonstr);
                Response response = _func(request); 
                std::string wjsonstr = response.Serialize();
                std::string wstr = Encode(wjsonstr);
                sockfd->Write(wstr);
            }
        }
    }


private:
    func_t _func;
};